/* 
 * File:   Player.cpp
 * Author: lucia
 * 
 * Created on 27 de octubre de 2014, 17:00
 */

#include "Player.h"

SBSLog* myLogFile;

Player::Player(ClientSocket* client) {
    //interaccion con el servidor.
    struct Event e;
    e.pressed = '@';
    this->pushEvent(e);
    this->client = client;
    this->init = true;
    this->semaforo = false; // !recv
    myLogFile->getInstance(MY_LOG_MODE);
    this->pack = 0;
    this->endThreads = false;

    this->waitingForStart = false;
}

struct ObjectInit Player::popObjects() {
    struct ObjectInit obj;
    obj = this->objects.waitAndPop();
    return obj;
}

void Player::pushObjects(struct ObjectInit obj) {
    this->objects.push(obj);

    //        cout << "SIZEEEEEEEEEEEEEEEEEEEEEEEE   " << this->objects.size() << endl;
}

void Player::communicationRecv() {
    int n;
    int timeOut = 8;
    while (this->isInit() && !this->endThreads) {
        struct ObjectInit obj;
        int length = sizeof (obj);
        n = this->client->recvTimeOut(&obj, length, timeOut);
        if (n == -1) {
//            cout << "Error recv" << endl;
            myLogFile->writeInLog(2, "[2] Error interno del socket al recibir elemento del mapa.\n");
            exit(1);
        }
        if (n == -2) {
//            cout << "El temporizador vencio de REcv" << endl;
            myLogFile->writeInLog(1, "[1] El server se desconecto mientras se recibía un elemento del mapa\n");
            this->setInit(false);
            break;
        }
        if (n == 0) {
//            cout << "Se fue el servidor" << endl;
            myLogFile->writeInLog(1, "[1] El server se desconecto mientras se recibía un elemento del mapa\n");
            this->setInit(false);
            break;
        }
        if (n != GARBAGE) {
            //            cout << "recv   "<< obj.idCharacter <<" " <<obj.objectId << " X: " <<obj.x << " Y: " <<obj.y<<endl;
            //            cout << "recv myObj.idCharacter-> " << obj.idCharacter << " myObj.objectId-> " << obj.objectId << " myObj.level-> " << obj.level << endl;
            if ((obj.idCharacter >= 0) && (obj.idCharacter < 22)) { //&& (obj.objectId >= 0) && (obj.objectId < 10)) {
                this->pushObjects(obj);

                if (!this->waitingForStart) {
                    if (obj.level == 1) {
                        this->endThreads = true;
                    }
                    if (obj.level == 2) {
                        this->endThreads = true;
                    }
                }
            }
        }
    }
//    cout << "fin hilo RECV" << endl;
    while (true) {
        usleep(1000000);
    }
//    cout << "fin hilo RECV Sleep" << endl;
}

void Player::communicationRecv2() {
//    cout << "reeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeecv level 2" << endl;
    int n;
    int timeOut = 8;
//    cout << "init hilo recv 222222222222" << endl;
    while (this->isInit() && !this->endThreads) {
        struct ObjectInit obj;
        int length = sizeof (obj);
        n = this->client->recvTimeOut(&obj, length, timeOut);
        if (n == -1) {
//            cout << "Error recv" << endl;
            myLogFile->writeInLog(2, "[2] Error interno del socket al recibir elemento del mapa.\n");
            exit(1);
        }
        if (n == -2) {
//            cout << "El temporizador vencio de REcv" << endl;
            myLogFile->writeInLog(1, "[1] El server se desconecto mientras se recibía un elemento del mapa\n");
            this->setInit(false);
            break;
        }
        if (n == 0) {
//            cout << "Se fue el servidor" << endl;
            myLogFile->writeInLog(1, "[1] El server se desconecto mientras se recibía un elemento del mapa\n");
            this->setInit(false);
            break;
        }
        if (n != GARBAGE) {
//            if ((obj.idCharacter < 10) && (obj.idCharacter > 0)){
//                        cout << "recv   "<< obj.idCharacter <<" " <<obj.objectId << " X: " <<obj.x << " Y: " <<obj.y<<endl;
//            }
            this->pushObjects(obj);
            if (obj.level == 1) {
//                cout << "seeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeet" << endl;
                this->endThreads = true;
            }
            if (obj.level == 2) {
//                cout << "Characterid: " << obj.idCharacter << endl;
//                cout << "ObjectId" << obj.objectId << endl;
                this->endThreads = true;
            }
        }
    }
//    cout << "fin hilo RECV 22222222222" << endl;
    //aveces el cliente se muere cuando sale de este metodo. Es una solucion rapida.
    while (true) {
        usleep(1000000);
    }

//    cout << "fin hilo RECV Sleep" << endl;
}

void Player::setEndThreads(bool threadstate){
    this->endThreads=threadstate;
}

int Player::getCantPack() {
    int dev = this->pack;
    this->pack = 0;
    return dev;
    //        retun = this->objects.size();
}

struct Event Player::popEvent() {
    struct Event e;
    e = this->events.waitAndPop();
    return e;
}

void Player::pushEvent(struct Event event) {
    //    cout << "pusheooooooooo " <<event.pressed << "    " << event.released <<endl;
    this->events.push(event);
}

void Player::communicationSend() {
    int n;
    while (this->isInit() && !this->endThreads) { //mientras que el player este vivo y endThreads=false       
        //Aca habria que popear de la cola bloqueante 
        struct Event myE;
        myE = this->popEvent();
        //        if (myE.pressed != '@'){
        int length = sizeof (myE);
        n = this->client->sendAll(&myE, length);
        if (n == -1) {
//            cout << "Error enviar" << endl;
            myLogFile->writeInLog(2, "[2] Error interno del socket al enviar evento al server.\n");
            exit(1);
        }
        if (n == 0) {
//            cout << "Cliente->desconectar." << endl;
            myLogFile->writeInLog(1, "[1] El server se desconecto mientras se le enviaba un evento\n");
            this->setInit(false);
            break;
        } else {
            //            cout << "se enviooooo" <<endl;
        }
        //        }
    }
    while (true) {
        usleep(1000000);
    }
//    cout << "fin hilo SEND" << endl;
}

void Player::runThreadRecv() {
    this->endThreads = false;
    //    std::thread threadRecv(&Player::communicationRecv, this);
    //    std::swap(thread, this->threadRecv);
    this->threads.push_back(std::thread(&Player::communicationRecv, this));

}

void Player::runThreadSend() {
    this->endThreads = false;
    //    std::thread threadSend(&Player::communicationSend, this);
    //    std::swap(thread, this->threadSend);
    this->threads.push_back(std::thread(&Player::communicationSend, this));
}

void Player::runThreadRecv2() {
    this->endThreads = false;
    //    std::thread thread(&Player::communicationRecv, this);
    //    std::swap(thread, this->threadRecv2);
    this->threads.push_back(std::thread(&Player::communicationRecv2, this));
}

void Player::runThreadSend2() {
    this->endThreads = false;
    //    std::thread thread(&Player::communicationSend, this);
    //    std::swap(thread, this->threadSend2);
    this->threads.push_back(std::thread(&Player::communicationSend, this));
}

bool Player::isInit() {
    return this->init;
}

void Player::setInit(bool flag) {
    this->init = flag;
}

void Player::setWaitForReloadGame(int flag){
    if (flag == 0){
        this->waitingForStart = false;
    } else if (flag == 1){
        this->waitingForStart = true;
    }
}

bool Player::tryPop(struct ObjectInit & obj) {
    bool r = this->objects.tryPop(obj);
    
//    cout << "size object inittttttttttttttttttttttt" << this->objects.size() << endl;
//    cout << "obj "<< obj.objectId<<endl;
    return r;
}

Player::~Player() {
    //    cout << "Destructor de player\n";
}
